# @file    : tr
# @time    : 2025/5/30
# @author  : yongpeng.yao
# @desc    :

import re
from typing import Dict, Pattern

from fastapi.exceptions import RequestValidationError
from pydantic_i18n import PydanticI18n
from starlette.responses import JSONResponse
from starlette.status import HTTP_422_UNPROCESSABLE_ENTITY

__all__ = ["get_locale", "validation_exception_handler"]

DEFAULT_LOCALE = "zh_CN"

translations = {
    "en_US": {
        "Field required": "field required",
    },
    "zh_CN": {
        "Object has no attribute '{}'": "对象没有属性 '{}'",
        "Invalid JSON: {}": "无效的JSON数据: {}",
        "JSON input should be string, bytes or bytearray": "JSON输入应为字符串、字节或字节数组",
        "Cannot check `{}` when validating from json, use a JsonOrPython validator instead": "从json验证时无法检查`{}`，请改用JsonOrPython验证器",
        "Recursion error - cyclic reference detected": "递归错误-检测到循环引用",
        "Field required": "字段必填",
        "Field is frozen": "字段已被冻结",
        "Instance is frozen": "实例已被冻结",
        "Extra inputs are not permitted": "不允许额外的输入",
        "Keys should be strings": "键名应为字符串",
        "Error extracting attribute: {}": "提取属性时出错: {}",
        "Input should be a valid dictionary or instance of {}": "输入应为有效的字典或{}的实例",
        "Input should be a valid dictionary or object to extract fields from": "输入应为有效的字典或可提取字段的对象",
        "Input should be a dictionary or an instance of {}": "输入应为字典或{}的实例",
        "Input should be an instance of {}": "输入应为{}的实例",
        "Input should be None": "输入应为None",
        "Input should be greater than {}": "输入应大于{}",
        "Input should be greater than or equal to {}": "输入应大于等于{}",
        "Input should be less than {}": "输入应小于{}",
        "Input should be less than or equal to {}": "输入应小于等于{}",
        "Input should be a multiple of {}": "输入应为{}的倍数",
        "Input should be a finite number": "输入应为有限数字",
        "Input should be iterable": "输入应为可迭代对象",
        "Error iterating over object, error: {}": "迭代对象时出错: {}",
        "Input should be a valid string": "输入应为有效的字符串",
        "Input should be a string, not an instance of a subclass of str": "输入应为字符串，而不是str子类的实例",
        "Input should be a valid string, unable to parse raw data as a unicode string": "输入应为有效的字符串，无法将原始数据解析为unicode字符串",
        "String should have at least {}": "字符串长度至少为{}",
        "String should have at most {}": "字符串长度最多为{}",
        "String should match pattern '{}'": "字符串应匹配模式'{}'",
        "Input should be {}": "输入应为{}",
        "Input should be a valid dictionary": "输入应为有效的字典",
        "Input should be a valid mapping, error: {}": "输入应为有效的映射，错误: {}",
        "Input should be a valid list": "输入应为有效的列表",
        "Input should be a valid tuple": "输入应为有效的元组",
        "Input should be a valid set": "输入应为有效的集合",
        "Set items should be hashable": "集合元素应为可哈希对象",
        "Input should be a valid boolean": "输入应为有效的布尔值",
        "Input should be a valid boolean, unable to interpret input": "输入应为有效的布尔值，无法解析输入",
        "Input should be a valid integer": "输入应为有效的整数",
        "Input should be a valid integer, unable to parse string as an integer": "输入应为有效的整数，无法将字符串解析为整数",
        "Unable to parse input string as an integer, exceeded maximum size": "无法将输入字符串解析为整数，超过最大长度限制",
        "Input should be a valid integer, got a number with a fractional part": "输入应为有效的整数，但包含小数部分",
        "Input should be a valid number": "输入应为有效的数字",
        "Input should be a valid number, unable to parse string as a number": "输入应为有效的数字，无法将字符串解析为数字",
        "Input should be a valid bytes": "输入应为有效的字节",
        "Data should have at least {}": "数据长度至少为{}",
        "Data should have at most {}": "数据长度最多为{}",
        "Data should be valid {}": "数据应为有效的{}",
        "Value error, {}": "数值错误, {}",
        "Assertion failed, {}": "断言失败, {}",
        "Input should be a valid date": "输入应为有效的日期",
        "Input should be a valid date in the format YYYY-MM-DD, {}": "输入应为YYYY-MM-DD格式的有效日期, {}",
        "Input should be a valid date or datetime, {}": "输入应为有效的日期或时间, {}",
        "Datetimes provided to dates should have zero time - e.g. be exact dates": "提供给日期的日期时间应没有时间部分(即精确日期)",
        "Date should be in the past": "日期应为过去时间",
        "Date should be in the future": "日期应为未来时间",
        "Input should be a valid time": "输入应为有效的时间",
        "Input should be in a valid time format, {}": "输入应为有效的时间格式, {}",
        "Input should be a valid datetime": "输入应为有效的日期时间",
        "Input should be a valid datetime, {}": "输入应为有效的日期时间, {}",
        "Invalid datetime object, got {}": "无效的日期时间对象, 得到{}",
        "Input should be a valid datetime or date, {}": "输入应为有效的日期时间或日期, {}",
        "Input should be in the past": "输入应为过去时间",
        "Input should be in the future": "输入应为未来时间",
        "Input should not have timezone info": "输入不应包含时区信息",
        "Input should have timezone info": "输入应包含时区信息",
        "Timezone offset of {}": "时区偏移量为{}",
        "Input should be a valid timedelta": "输入应为有效的时间差",
        "Input should be a valid timedelta, {}": "输入应为有效的时间差, {}",
        "Input should be a valid frozenset": "输入应为有效的不可变集合",
        "Input should be a subclass of {}": "输入应为{}的子类",
        "Input should be callable": "输入应为可调用对象",
        "Input tag '{}": "输入标签'{}",
        "Unable to extract tag using discriminator {}": "无法使用鉴别器{}提取标签",
        "Arguments must be a tuple, list or a dictionary": "参数应为元组、列表或字典",
        "Missing required argument": "缺少必需参数",
        "Unexpected keyword argument": "意外的关键字参数",
        "Missing required keyword only argument": "缺少必需的关键字参数",
        "Unexpected positional argument": "意外的位置参数",
        "Missing required positional only argument": "缺少必需的位置参数",
        "Got multiple values for argument": "参数有多个值",
        "URL input should be a string or URL": "URL输入应为字符串或URL对象",
        "Input should be a valid URL, {}": "输入应为有效的URL, {}",
        "Input violated strict URL syntax rules, {}": "输入违反了严格的URL语法规则, {}",
        "URL should have at most {}": "URL长度最多为{}",
        "URL scheme should be {}": "URL协议应为{}",
        "UUID input should be a string, bytes or UUID object": "UUID输入应为字符串、字节或UUID对象",
        "Input should be a valid UUID, {}": "输入应为有效的UUID, {}",
        "UUID version {} expected": "应为版本{}的UUID",
        "Decimal input should be an integer, float, string or Decimal object": "Decimal输入应为整数、浮点数、字符串或Decimal对象",
        "Input should be a valid decimal": "输入应为有效的十进制数",
        "Decimal input should have no more than {} in total": "Decimal输入总位数不应超过{}",
        "Decimal input should have no more than {}": "Decimal输入小数位数不应超过{}",
        "Decimal input should have no more than {} before the decimal point": "Decimal输入小数点前位数不应超过{}",
        "Input should be a valid python complex object, a number, or a valid complex string following the rules at https://docs.python.org/3/library/functions.html#complex": "输入应为有效的python复数对象、数字或符合https://docs.python.org/3/library/functions.html#complex规则的复数字符串",
        "Input should be a valid complex string following the rules at https://docs.python.org/3/library/functions.html#complex": "输入应为符合https://docs.python.org/3/library/functions.html#complex规则的复数字符串"
    },
}


class MyPydanticI18n(PydanticI18n):

    def _init_pattern(self) -> Pattern[str]:
        keys = [key for key in self.source.get_translations(self.default_locale) if '{}' in key]
        keys = sorted(keys, key=len, reverse=True)
        return re.compile(
            "|".join("({})".format(re.escape(i).replace(r"\{\}", "(.+)")) for i in keys)
        )

    def _translate(self, message: str, locale: str) -> str:
        if locale not in self.locales:
            raise ValueError(f"Locale '{locale}' wasn't found.")
        if message in self.source.get_translations(locale):
            return self.source.gettext(message, locale)

        return super()._translate(message, locale)


tr = MyPydanticI18n(translations, default_locale=DEFAULT_LOCALE)


def get_locale(locale: str = DEFAULT_LOCALE) -> str:
    return locale


async def validation_exception_handler(
        _,
        exc: RequestValidationError
) -> JSONResponse:
    return JSONResponse(
        status_code=HTTP_422_UNPROCESSABLE_ENTITY,
        content={"detail": tr.translate(exc.errors(), DEFAULT_LOCALE)},
    )


http_status_codes: Dict[int, str] = {
    # 客户端错误 (4xx)
    400: "错误请求（服务器无法理解的请求）",
    401: "未授权（需要身份验证）",
    402: "需要支付（保留用于未来支付系统）",
    403: "禁止访问（服务器拒绝执行请求）",
    404: "未找到（资源不存在）",
    405: "方法不允许（禁用请求中指定的方法）",
    406: "不可接受（无法生成客户端可接受的内容）",
    407: "需要代理认证（类似401但需代理认证）",
    408: "请求超时（服务器等待请求超时）",
    409: "冲突（请求与资源当前状态冲突）",
    410: "已删除（资源已永久删除）",
    411: "需要长度（请求需要Content-Length头）",
    412: "前置条件失败（请求头中条件不满足）",
    413: "请求实体过大（请求体超过服务器限制）",
    414: "URI过长（请求URI超过服务器限制）",
    415: "不支持的媒体类型（服务器无法处理请求格式）",
    416: "范围无效（请求范围无法满足）",
    417: "预期失败（无法满足Expect请求头）",
    418: "我是茶壶（愚人节玩笑代码）",
    421: "错误定向请求（请求被定向到无法响应的服务器）",
    422: "无法处理的实体（请求格式正确但语义错误）",
    423: "已锁定（WebDAV：资源被锁定）",
    424: "依赖失败（WebDAV：因前序请求失败导致当前失败）",
    425: "过早请求（服务器不愿处理可能重播的请求）",
    426: "需要升级（客户端应切换协议）",
    428: "需要前置条件（请求必须包含条件头）",
    429: "请求过多（客户端发送过多请求）",
    431: "请求头字段过大（请求头超出服务器限制）",
    451: "因法律原因不可用（服务器因法律要求无法提供资源）",

    # 服务器错误 (5xx)
    500: "服务器内部错误（服务器遇到意外错误）",
    501: "未实现（服务器不支持请求的功能）",
    502: "错误网关（网关或代理从上游服务器收到无效响应）",
    503: "服务不可用（服务器暂时过载或维护）",
    504: "网关超时（网关或代理等待上游服务器响应超时）",
    505: "HTTP版本不支持（服务器不支持请求的HTTP版本）",
    506: "变种也可协商（服务器存在内部配置错误）",
    507: "存储空间不足（WebDAV：无法存储完成请求所需内容）",
    508: "检测到循环（WebDAV：操作导致无限循环）",
    510: "未扩展（请求需要扩展但服务器不支持）",
    511: "需要网络认证（客户端需要认证才能访问网络）"
}
